package org.ainlolcat.ainscience.matrix;

import org.ainlolcat.Variable;
import org.ainlolcat.aincalc2.*;
import org.ainlolcat.ainscience.Controller;
import org.ainlolcat.ainscience.column.ColumnImpl;
import org.ainlolcat.ainscience.entity.links.Link;
import org.ainlolcat.ainscience.tools;
import org.ainlolcat.ainscience.utils.executor.Executor;
import org.ainlolcat.ainscience.utils.executor.ExecutorProvider;
import org.apache.log4j.Logger;
import org.jdom.Element;

import java.util.*;
import java.util.regex.Pattern;


/**
 * @author ainlolcat
 * Date: 11/10/11
 * todo matrix calculation almost the same as matrix
 */
public class MatrixCalculator{
    private static Logger log = Logger.getLogger(MatrixCalculator.class);
    Matrix matrix;
    List<Element> calcCols;
    Map<String, HashMap<String, Element>> missings = new HashMap();
    Map<String, Link> links;

    /**
     * perform calculations on Columns. Uses links API so not safe in future
     * @param matrix
     * @return
     */
    public Matrix calculate(Matrix matrix, Element parseInfo, Map<String, Link> links){
        this.matrix = matrix;
        this.links = links;
        calcCols = parseInfo.getChild("calculated")==null?
                                    new ArrayList<Element>():
                                    parseInfo.getChild("calculated").getChildren("column");
        for (Element ecolumn : calcCols){
            handleCalculatedElement(ecolumn);
        }
        return matrix;
    }

    static Pattern valuesPattern = Pattern.compile("val\\((\\w*):\\d*\\)");
    static Pattern columnLinkPattern = Pattern.compile("val\\((\\w*):\\d*\\)");
    private void handleCalculatedElement(Element ecolumn ){
        String name = ecolumn.getAttributeValue("name");
        String id = ecolumn.getAttributeValue("id");
        String axis = ecolumn.getAttributeValue("axis");
        String type = ecolumn.getAttributeValue("type");
        String formula = ecolumn.getAttributeValue("formula");
        if (formula!=null){
            ColumnImpl column = new ColumnImpl(name);
            column.setAxis(axis);
            column.setType(tools.parseInteger(type));

            int rowCount = matrix.getRowCount();
            List values = new ArrayList();

            Executor executor = ExecutorProvider.getExecutor(new MatrixEntityWrapper(matrix, links));
            for (int i=0;i<rowCount;i++){
                executor.getFunctionExecutor().setRow(i);
                Object value =  executor.execute(formula).getStringValue();
                values.add(value);
            }
            column.setValues(values);
            matrix.setColumn(tools.parseInteger(id), column);
        }
    }
}
